package com.bilibili.juc.atomic;

import lombok.Data;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

/**
 * @author zuife
 * @description 以一种线程安全的方式操作非线程安全对象的某些字段
 * <p>
 * 需求：
 * 10个线程，
 * 每个线程转账1000，
 * 不使用synchronized，尝试使用atomicIntegerFieldUpdater来实现
 * @since 2024-05-04 20:46:17
 */
public class AtomicIntegerFieldUpdaterDemo {
    public static void main(String[] args) {
        BankAccount bankAccount = new BankAccount();
        CountDownLatch countDownLatch = new CountDownLatch(10);
        for (int i = 0; i < 10; i++) {
            new Thread(() -> {
                try {
                    for (int j = 0; j < 1000; j++) {
                        bankAccount.transMoney(bankAccount);
                    }
                } finally {
                    countDownLatch.countDown();
                }
            }, String.valueOf(i)).start();

        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println(bankAccount.getMoney());
    }
}

@Data
class BankAccount {
    // 使用public volatile关键字修饰
    public volatile int money = 0;
    String bankName = "CCB";

    /**
     * @param BankAccount 要更新的字段所属的类
     * @param "money" 要更新的字段名
     * @return 返回一个初始化好的AtomicIntegerFieldUpdater实例，用于更新BankAccount类中的money字段
     */
    AtomicIntegerFieldUpdater<BankAccount> moneyUpdater = AtomicIntegerFieldUpdater.newUpdater(BankAccount.class, "money");

    //不加Synchronized, 保证高性能原子性，局部微创小手术
    public void transMoney(BankAccount bankAccount) {
        moneyUpdater.getAndIncrement(bankAccount);
    }
}